/*
 * tsock.h
 *
 *  Created on: 2011-08-16
 *      Author: Baron Wang
 */

#ifndef TSOCK_H_
#define TSOCK_H_

#include <sys/socket.h>
#include <netinet/in.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * tsock provides a common wrapper for the TCP/UDP/SCTP via IPv4 and IPv6
 *
 * Please note that if want SCTP, need to recompile with _SCTP enabled.
 *
 * Also, if user want to do something about socket, it is highly preferred to
 * check this header file to see if it has the methord.
 *
 * About the peer description, tsock_ep is STRONGLY recommanded using because
 * it can cover both IPv4 or IPv6 combined with other tsock APIs.
 *
 */

#define IN
#define OUT

#define SYS_UDP              IPPROTO_UDP
#define SYS_TCP              IPPROTO_TCP

#ifdef _SCTP
#define SYS_SCTP             IPPROTO_SCTP
#else
#define SYS_SCTP             132
#define SCTP_NODELAY         3
#endif

#define SYS_INVALID          0xFA

typedef union {
    struct sockaddr          sa;
    struct sockaddr_in       sa_in;
    struct sockaddr_in6      sa_in6;
    struct sockaddr_storage  sa_sto;
} t_sockaddr;

typedef union {
    struct sockaddr          *psa;
    struct sockaddr_in       *psa_in;
    struct sockaddr_in6      *psa_in6;
    struct sockaddr_storage  *psa_sto;
} p_sockaddr;

typedef union {
    struct in_addr           addr_4;    /* the IPv4 address     */
    struct in6_addr          addr_6;    /* the IPv6 address     */
} t_addr;

/* suggest to memset before use */
typedef struct{
    sa_family_t              type;      /* AF_INET/AF_INET6     */
    uint8_t                  prtl;      /* the protocol         */
    in_port_t                port;      /* the socket port      */
    t_addr                   addr;      /* the socket address   */
#define v4addr               addr.addr_4
#define v6addr               addr.addr_6
} tsock_ep;

/*
 * Description:
 *         inline function for the internal print
 */
const char* prtl_to_str(IN const int protocol);
const char* type_to_str(IN const int ip_type);

/*
 * Description:
 *         A simple reset to make the the protocol to 250 (0xFA)
 *         0xFF can not be used because it is RAW SOCKET
 * NOTE:
 *         No defensive check.
 */
void reset_ep(IN tsock_ep *endpoint);

/*
 * Description:
 *         Check if the endpoint is inited
 * Note:
 *         return value
 *             1 = TRUE, as init
 *             0 = FALSE, if NULL, also return 0
 */
int is_ep_init(IN const tsock_ep *endpoint);

/*
 * Description:
 *         Check if the endpoint is a multicast ep
 * Note:
 *         return value
 *             1 = TRUE, as init
 *             0 = FALSE, if NULL, also return 0
 */
int is_multicast(IN const tsock_ep *endpoint);

/*
 * Description:
 *         This is the function to convert a user string(sz), protocol and
 *         port to a tsock_ep structure.
 *
 *         IPv4address = a, a.b, a.b.c, a.b.c.d
 *             a, b, c, d is all 1~3 digits
 *
 *         IPv6address = hexpart [ ":" IPv4address ]
 *             hexpart = hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ]
 *             hexseq = hex4 *( ":" hex4)
 *             ex4 = 1*4HEXDIG
 *
 * NOTE:
 *         1, the IP type (v4 or v6) will be automatically filled by value.
 *         2, it does NOT support IP:PORT type such as 127.0.0.1:80
 *         3, NO check for endpoint null pointer, MUST be valid
 *
 * Parameters:
 *         addr_sz        - Zero ended string, such as '127.0.0.1\0';
 *         protocol    - SYS_UDP, SYS_TCP or SYS_SCTP
 *         port        - IP port
 *         endpoint    - The endpoint to be filled, MUST be valid
 *
 * Return:
 *         0             -    Sueccess
 *        -1             -    Fail
 */
int addr_to_ep(IN const char* addr_sz, IN int protocol, IN in_port_t port,
    OUT tsock_ep *endpoint);


/*
 * Description:
 *         This function converts the IP address to the indicated buffer
 *
 * NOTE:
 *         1, NO defensive check for endpoint
 *         2, NO defensive check for buf
 *         3, INET6_ADDRSTRLEN + 1 is preferred to use for the size
 *
 * Parameters:
 *        endpoint    - The endpoint to be converted
 *        buf            - String buffer outside, must be valid
 *        size        - the buf size passed in
 *
 * Return:
 *         The pointer to the OUT buf if suessfull, NULL or else
 */
const char* ep_to_addr(IN const tsock_ep *endpoint, OUT char* buf,
    IN int size);


/*
 * Description:
 *         This function convers a sockaddr and IP type to the endpoint
 *
 * NOTE:
 *         1, No defensive check for addr
 *         2, No defensive check for ep
 *
 * Parameters:
 *         addr        - The network order address
 *         protocol    - SYS_UDP, SYS_TCP or SYS_SCTP
 *         ep            - indicated endpoint to be modified
 *
 * Return:
 *         0             -    Sueccess
 *        -1             -    Fail
 */
int sockaddr_to_ep(IN const struct sockaddr *addr, IN int protocol,
    OUT tsock_ep *ep);


#ifdef __cplusplus
}
#endif

#endif /* SYSSOCK_H_ */
